﻿using System;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI.WebControls;
using Framework.Library.Core.Utils.GlobalHelper;

namespace Framework.Library.Core.Utils
{
    public class MiscUtility
    {
        public const int COMMAND_LENGTH = 5;

        public static string OptimiseHtml(string strInput)
        {
            if (strInput.Length > 400)
            {
                string temp = strInput.Substring(0, 400);
                temp =
                    temp.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("\n\r", "").Replace("\r\n", "").
                        Replace("\"", "\"\"");
                strInput = temp.Substring(0, temp.LastIndexOf(" ")) + "...";
            }
            else
            {
                strInput =
                    strInput.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("\n\r", "").Replace("\r\n",
                                                                                                               "").
                        Replace("\"", "\"\"");
            }
            return strInput;
        }

        public static string SafeHtmlToText(string s)
        {
            string tmp = s;
            tmp = tmp.Replace(((char) 13).ToString(), String.Empty);
            tmp = tmp.Replace(((char) 10).ToString(), String.Empty);
            tmp = CaseInsensitiveReplace(tmp, "<br>", ((char) 13).ToString());

            bool isTag = false;
            string retVal = String.Empty;
            for (int i = 0; i < tmp.Length; i++)
            {
                switch (tmp[i])
                {
                    case '<':
                        isTag = true;
                        break;
                    case '>':
                        isTag = false;
                        break;
                    default:
                        if (!isTag)
                            retVal += tmp[i];
                        break;
                }
            }
            return HttpUtility.HtmlDecode(retVal);
        }

        public static string CaseInsensitiveReplace(string s, string sold, string snew)
        {
            string retVal, searchStr, patt, newStr;
            int offset;

            searchStr = s.ToLower();
            patt = sold.ToLower();

            newStr = s;
            retVal = String.Empty;

            while (searchStr != String.Empty)
            {
                offset = searchStr.IndexOf(patt);
                if (offset == -1)
                {
                    retVal += newStr;
                    break;
                }

                retVal += newStr.Substring(0, offset) + snew;
                newStr = newStr.Remove(0, offset + sold.Length);
                searchStr = searchStr.Remove(0, offset + patt.Length);
            }
            return retVal;
        }

        public static string ToolTip1(string headline, string avatar, string teaser, string alias, DateTime datetime)
        {
            string _datetime = "";
            _datetime += " Update at : " + datetime.Hour + ":" + datetime.Minute + " - " +
                         datetime.ToString("dd/MM/yyyy");
            if (alias != "")
            {
                alias = alias + " - ";
            }

            string tooltip = "";
            tooltip += "<table width=\"322px\" cellpadding=\"1\" cellspacing=\"0\">";
            tooltip += "    <tr>";
            tooltip += "        <td align=\"left\" style=\"text-align:justify\"><b>";
            tooltip += OptimiseHtml(headline);
            tooltip += "        </b></td>";
            tooltip += "    </tr>";
            tooltip += "    <tr>";
            tooltip +=
                "        <td align=\"left\" style=\"text-align:justify;color:#777777;font-size:10px;font-name:tahoma;\">";
            tooltip += alias + _datetime;
            tooltip += "        </td>";
            tooltip += "    </tr>";
            tooltip += "    <tr>";
            tooltip += "        <td style=\"text-align:justify\">";
            if (avatar != "")
            {
                tooltip += "            <table style=\"float:left\">";
                tooltip += "                <tr>";
                tooltip += "                    <td>";
                tooltip += "                         <img style=\"border:solid 1px #07519A;\" src=\"" + avatar +
                           "\" witdh=\"75\" />";

                tooltip += "                    </td>";
                tooltip += "                </tr>";
                tooltip += "            </table>";
            }

            tooltip += RemoveNewLines(SafeHtmlToText(StripHTML(teaser).Replace("'", "").Trim()).Replace(@"\", ""));
            tooltip += "        </td>";
            tooltip += "    </tr>";
            tooltip += "</table>";

            return tooltip;
        }

        public static string OptimiseContent(string source)
        {
            try
            {
                string result;

                // Remove HTML Development formatting
                result =
                    source.Replace("\r", " ").Replace("\n", "").Replace("\t", "").Replace("\n\r", "").Replace("\r\n", "")
                        .Replace("\"", "\"\""); // Replace line breaks with space because browsers inserts space
                result = result.Replace("<strong>", "").Replace("</strong>", "").Replace("<b>", "").Replace("</b>", "");
                result = Regex.Replace(result, @"( )*font([^>])*", "", RegexOptions.IgnoreCase);
                result = result.Replace("</font>", "");
                result = Regex.Replace(result, "( )*style=\\\"font([^>])*", "", RegexOptions.IgnoreCase);

                result = Regex.Replace(result, @"<p>", "", RegexOptions.IgnoreCase);
                result = result.Replace("</p>", "");

                result = result.Replace("<br>", "");

                result = Regex.Replace(result, @"<span>", "", RegexOptions.IgnoreCase);
                result = result.Replace("</span>", "");

                result = Regex.Replace(result, @"<div>", "", RegexOptions.IgnoreCase);
                result = result.Replace("</div>", "");

                return result;
            }
            catch
            {
                return source;
            }
        }

        public static string StripHTML(string source)
        {
            try
            {
                string result;

                // Remove HTML Development formatting
                result = source.Replace("\r", " "); // Replace line breaks with space because browsers inserts space
                result = result.Replace("\n", " "); // Replace line breaks with space because browsers inserts space
                result = result.Replace("\t", string.Empty); // Remove step-formatting
                result = Regex.Replace(result, @"( )+", " "); // Remove repeating speces becuase browsers ignore them

                // Remove the header (prepare first by clearing attributes)
                result = Regex.Replace(result, @"<( )*head([^>])*>", "<head>", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"(<( )*(/)( )*head( )*>)", "</head>", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, "(<head>).*(</head>)", string.Empty, RegexOptions.IgnoreCase);

                // remove all scripts (prepare first by clearing attributes)
                result = Regex.Replace(result, @"<( )*script([^>])*>", "<script>", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"(<( )*(/)( )*script( )*>)", "</script>", RegexOptions.IgnoreCase);
                //result = System.Text.RegularExpressions.Regex.Replace(result, @"(<script>)([^(<script>\.</script>)])*(</script>)",string.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"(<script>).*(</script>)", string.Empty, RegexOptions.IgnoreCase);

                // remove all styles (prepare first by clearing attributes)
                result = Regex.Replace(result, @"<( )*style([^>])*>", "<style>", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"(<( )*(/)( )*style( )*>)", "</style>", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, "(<style>).*(</style>)", string.Empty, RegexOptions.IgnoreCase);

                // insert tabs in spaces of <td> tags
                result = Regex.Replace(result, @"<( )*td([^>])*>", "\t", RegexOptions.IgnoreCase);

                // insert line breaks in places of <BR> and <LI> tags
                result = Regex.Replace(result, @"<( )*br( )*>", "\r", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"<( )*li( )*>", "\r", RegexOptions.IgnoreCase);

                // insert line paragraphs (double line breaks) in place if <P>, <DIV> and <TR> tags
                result = Regex.Replace(result, @"<( )*div([^>])*>", "\r\r", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"<( )*tr([^>])*>", "\r\r", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"<( )*p([^>])*>", "\r\r", RegexOptions.IgnoreCase);

                // Remove remaining tags like <a>, links, images, comments etc - anything thats enclosed inside < >
                result = Regex.Replace(result, @"<[^>]*>", string.Empty, RegexOptions.IgnoreCase);

                // replace special characters:
                result = Regex.Replace(result, @"&nbsp;", " ", RegexOptions.IgnoreCase);

                result = Regex.Replace(result, @"&bull;", " * ", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&lsaquo;", "<", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&rsaquo;", ">", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&trade;", "(tm)", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&frasl;", "/", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&lt;", "<", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&gt;", ">", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&copy;", "(c)", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, @"&reg;", "(r)", RegexOptions.IgnoreCase);
                // Remove all others. More can be added, see http://hotwired.lycos.com/webmonkey/reference/special_characters/
                result = Regex.Replace(result, @"&(.{2,6});", string.Empty, RegexOptions.IgnoreCase);

                // for testng
                //System.Text.RegularExpressions.Regex.Replace(result, this.txtRegex.Text,string.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase);

                // make line breaking consistent
                result = result.Replace("\n", "\r");

                // Remove extra line breaks and tabs: replace over 2 breaks with 2 and over 4 tabs with 4. 
                // Prepare first to remove any whitespaces inbetween the escaped characters and remove redundant tabs inbetween linebreaks
                result = Regex.Replace(result, "(\r)( )+(\r)", "\r\r", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, "(\t)( )+(\t)", "\t\t", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, "(\t)( )+(\r)", "\t\r", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, "(\r)( )+(\t)", "\r\t", RegexOptions.IgnoreCase);
                result = Regex.Replace(result, "(\r)(\t)+(\r)", "\r\r", RegexOptions.IgnoreCase);
                    // Remove redundant tabs
                result = Regex.Replace(result, "(\r)(\t)+", "\r\t", RegexOptions.IgnoreCase);
                    // Remove multible tabs followind a linebreak with just one tab
                string breaks = "\r\r\r"; // Initial replacement target string for linebreaks
                string tabs = "\t\t\t\t\t"; // Initial replacement target string for tabs
                for (int index = 0; index < result.Length; index++)
                {
                    result = result.Replace(breaks, "\r\r");
                    result = result.Replace(tabs, "\t\t\t\t");
                    breaks = breaks + "\r";
                    tabs = tabs + "\t";
                }

                // Thats it.
                return result;
            }
            catch
            {
                //MessageBox.Show("Error");
                return source;
            }
        }

        public static string RemoveNewLines(string input, bool addSpace)
        {
            string replace = string.Empty;
            if (addSpace)
                replace = " ";

            string pattern = @"[\r|\n]";
            var regEx = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);

            return regEx.Replace(input, replace);
        }

        public static string RemoveNewLines(string input)
        {
            return RemoveNewLines(input, false);
        }

        public static string Alert(string strAlert)
        {
            return "return confirm('" + strAlert + "')";
        }

        public static string UpdateQueryStringItem(string url, string queryStringKey, string newQueryStringValue)
        {
            return UpdateQueryStringItem(url, queryStringKey, newQueryStringValue, false);
        }

        public static string UpdateQueryStringItem(string url, string queryStringKey, string newQueryStringValue,
                                                   bool rewrite)
        {
            var NewURL = new StringBuilder();

            NewURL.Append(url);

            if (url.IndexOf("?" + queryStringKey + "=") >= 0 || url.IndexOf("&" + queryStringKey + "=") >= 0)
            {
                int start = url.IndexOf(queryStringKey) + queryStringKey.Length + 1;
                int end = url.IndexOf('&', start);
                end = end < 0 ? url.Length : end;
                string val = url.Substring(start, end - start);

                string OrignalSet;
                string NewSet;
                OrignalSet = String.Format("{0}/{1}", queryStringKey, val);
                if (url.IndexOf(OrignalSet) > 0)
                {
                    NewSet = String.Format("{0}/{1}", queryStringKey, newQueryStringValue);
                }
                else
                {
                    OrignalSet = String.Format("{0}={1}", queryStringKey, val);
                    NewSet = String.Format("{0}={1}", queryStringKey, newQueryStringValue);
                }

                NewURL.Replace(OrignalSet, NewSet);
            }
            else if (url.IndexOf("/?") < 0 && (url.IndexOf("aspx?") < 0 || url.IndexOf("html?") < 0))
                //? html thi lam the nao
            {
                if (rewrite)
                    NewURL.Replace(".html", string.Format("/{0}/{1}.html", queryStringKey, newQueryStringValue));
                else
                    NewURL.AppendFormat("?{0}={1}", queryStringKey, newQueryStringValue);
            }
            else
            {
                if (rewrite)
                    NewURL.Replace(".html", string.Format("/{0}/{1}.html", queryStringKey, newQueryStringValue));
                else
                    NewURL.AppendFormat("&{0}={1}", queryStringKey, newQueryStringValue);
            }

            return NewURL.ToString();
        }

        public static string UpdateQueryStringItem(HttpRequest httpRequest, string queryStringKey,
                                                   string newQueryStringValue)
        {
            return UpdateQueryStringItem(httpRequest, queryStringKey, newQueryStringValue, false);
        }

        public static string UpdateQueryStringItem(HttpRequest httpRequest, string queryStringKey,
                                                   string newQueryStringValue, bool rewrite)
        {
            var NewURL = new StringBuilder();

            NewURL.Append(httpRequest.RawUrl);

            if (httpRequest.QueryString[queryStringKey] != null)
            {
                string OrignalSet;
                string NewSet;
                OrignalSet = String.Format("{0}/{1}", queryStringKey, httpRequest.QueryString[queryStringKey]);
                if (httpRequest.RawUrl.IndexOf(OrignalSet) > 0)
                {
                    NewSet = String.Format("{0}/{1}", queryStringKey, newQueryStringValue);
                }
                else
                {
                    OrignalSet = String.Format("{0}={1}", queryStringKey, httpRequest.QueryString[queryStringKey]);
                    NewSet = String.Format("{0}={1}", queryStringKey, newQueryStringValue);
                }
                NewURL.Replace(OrignalSet, NewSet);
            }
            else if (httpRequest.RawUrl.IndexOf("/?") < 0 && httpRequest.RawUrl.IndexOf("aspx?") < 0)
            {
                if (rewrite)
                    NewURL.Replace(".html", string.Format("/{0}/{1}.html", queryStringKey, newQueryStringValue));
                else
                    NewURL.AppendFormat("?{0}={1}", queryStringKey, newQueryStringValue);
            }
            else
            {
                if (rewrite)
                    NewURL.Replace(".html", string.Format("/{0}/{1}.html", queryStringKey, newQueryStringValue));
                else
                    NewURL.AppendFormat("&{0}={1}", queryStringKey, newQueryStringValue);
            }

            return NewURL.ToString();
        }

        public static string UpdateQueryStringItem(HttpRequest httpRequest, string[] queryStringKeys,
                                                   string[] newQueryStringValues)
        {
            return UpdateQueryStringItem(httpRequest, queryStringKeys, newQueryStringValues, false);
        }

        public static string UpdateQueryStringItem(HttpRequest httpRequest, string[] queryStringKeys,
                                                   string[] newQueryStringValues, bool rewrite)
        {
            var NewURL = new StringBuilder();

            NewURL.Append(httpRequest.RawUrl.Replace("%20", " "));
            bool check = true;
            for (int i = 0; i < queryStringKeys.GetLength(0); i ++)
            {
                string queryStringKey = queryStringKeys[i];
                string newQueryStringValue = newQueryStringValues[i];
                if (httpRequest.QueryString[queryStringKey] != null)
                {
                    string OrignalSet;
                    string NewSet;
                    OrignalSet = String.Format("{0}/{1}", queryStringKey, httpRequest.QueryString[queryStringKey]);
                    if (httpRequest.RawUrl.IndexOf(OrignalSet) > 0)
                    {
                        NewSet = String.Format("{0}/{1}", queryStringKey, newQueryStringValue);
                    }
                    else
                    {
                        OrignalSet = String.Format("{0}={1}", queryStringKey, httpRequest.QueryString[queryStringKey]);
                        NewSet = String.Format("{0}={1}", queryStringKey, newQueryStringValue);
                    }
                    NewURL.Replace(OrignalSet, NewSet);
                }
                else if (httpRequest.RawUrl.IndexOf("/?") < 0 &&
                         (httpRequest.RawUrl.IndexOf("aspx?") < 0 || httpRequest.RawUrl.IndexOf("html?") < 0))
                {
                    if (newQueryStringValue != "" && newQueryStringValue != null)
                    {
                        if (check)
                        {
                            if (rewrite)
                                NewURL.Replace(".html",
                                               string.Format("/{0}/{1}.html", queryStringKey, newQueryStringValue));
                            else
                                NewURL.AppendFormat("?{0}={1}", queryStringKey, newQueryStringValue);
                            check = false;
                        }
                        else
                        {
                            if (rewrite)
                                NewURL.Replace(".html",
                                               string.Format("/{0}/{1}.html", queryStringKey, newQueryStringValue));
                            else
                                NewURL.AppendFormat("&{0}={1}", queryStringKey, newQueryStringValue);
                        }
                    }
                }
                else if (newQueryStringValue != "" && newQueryStringValue != null)
                {
                    if (rewrite)
                        NewURL.Replace(".html", string.Format("/{0}/{1}.html", queryStringKey, newQueryStringValue));
                    else
                        NewURL.AppendFormat("&{0}={1}", queryStringKey, newQueryStringValue);
                }
            }

            return NewURL.ToString();
        }

        public static void FillTreeData(ListItemCollection lst, DataTable dtCommands, string fieldKey, string fieldName,
                                        string fieldParentID, string sortBy)
        {
            lst.Clear();
            DataRow[] drRoots = dtCommands.Select(fieldParentID + "  = " + 0, sortBy);
            foreach (DataRow row in drRoots)
            {
                var item = new ListItem();
                item.Value = row[fieldKey].ToString();
                item.Text = row[fieldName].ToString();
                item.Attributes.Add("Level", "0");
                lst.Add(item);
                LoadCmdItem(lst, item, dtCommands, fieldKey, fieldName, fieldParentID, sortBy);
            }
        }

        private static void LoadCmdItem(ListItemCollection lst, ListItem curItem, DataTable dtCommands, string fieldKey,
                                        string fieldName, string fieldParentID, string sortBy)
        {
            int level = Convert.ToInt32(curItem.Attributes["Level"]);
            level += 1;
            int curID = Convert.ToInt32(curItem.Value);
            DataRow[] drChilds = dtCommands.Select(fieldParentID + " = " + curID);
            foreach (DataRow row in drChilds)
            {
                var childItem = new ListItem();
                childItem.Text = StringIndent(level) + row[fieldName];
                childItem.Value = row[fieldKey].ToString();
                childItem.Attributes.Add("Level", level.ToString());
                lst.Add(childItem);
                LoadCmdItem(lst, childItem, dtCommands, fieldKey, fieldName, fieldParentID, sortBy);
            }
        }

        public static void FillIndex(DropDownList dropIndex, int min, int max, int selected)
        {
            dropIndex.Items.Clear();
            for (int i = min; i <= max; i++)
            {
                var item = new ListItem(i.ToString(), i.ToString());
                if (i == selected) item.Selected = true;
                else item.Selected = false;
                dropIndex.Items.Add(item);
            }
        }

        public static void FillIndex(DropDownList dropIndex, int max, int selected)
        {
            dropIndex.Items.Clear();
            for (int i = 0; i <= max; i++)
            {
                var item = new ListItem(i.ToString(), i.ToString());
                if (i == selected) item.Selected = true;
                else item.Selected = false;
                dropIndex.Items.Add(item);
            }
        }

        public static void SelectItemFromList(ListControl list, string selectedValue)
        {
            list.SelectedIndex = -1;
            ListItem item = list.Items.FindByValue(selectedValue);
            if (item != null)
                item.Selected = true;
        }

        public static void SelectItemFromList(ListControl list, string[] selectedValues)
        {
            list.SelectedIndex = -1;
            for (int i = 0; i < selectedValues.Length; i ++)
            {
                string selectedValue = selectedValues[i];
                ListItem item = list.Items.FindByValue(selectedValue);
                if (item != null)
                    item.Selected = true;
            }
        }

        /// <summary>
        /// Sets the selected.
        /// </summary>
        /// <param name="lstItems">The LST items.</param>
        /// <param name="selectedValue">The selected value.</param>
        public static void SetSelected(ListItemCollection lstItems, string selectedValue)
        {
            ListItem item = lstItems.FindByValue(selectedValue);
            if (item != null) item.Selected = true;
        }

        /// <summary>
        /// Sets the selected.
        /// </summary>
        /// <param name="dropList">The drop list.</param>
        /// <param name="selectedValue">The selected value.</param>
        public static void SetSelected(DropDownList dropList, string selectedValue)
        {
            dropList.SelectedIndex = -1;
            SetSelected(dropList.Items, selectedValue);
        }

        /// <summary>
        /// Sets the selected.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <param name="selectedValue">The selected value.</param>
        public static void SetSelected(ListBox list, string selectedValue)
        {
            list.SelectedIndex = -1;
            SetSelected(list.Items, selectedValue);
        }

        /// <summary>
        /// Sets the selected.
        /// </summary>
        /// <param name="rdoList">The rdo list.</param>
        /// <param name="selectedValue">The selected value.</param>
        public static void SetSelected(RadioButtonList rdoList, string selectedValue)
        {
            rdoList.SelectedIndex = -1;
            SetSelected(rdoList.Items, selectedValue);
        }

        public static string StringIndent(int level)
        {
            string retVal = string.Empty;
            for (int i = 0; i < level; i ++)
                retVal += "....";
            return retVal;
        }

        public static string CreatePassword(int length)
        {
            string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!#%&()@${[]}";
            string res = "";
            var rnd = new Random();
            while (0 < length--)
                res += valid[rnd.Next(valid.Length)];
            return res;
        }

        public static string CreateCommand()
        {
            string valid = "abcdefghijklmnopqrstuvwxyz";
            string res = "";
            var rnd = new Random();
            for (int i = 0; i < COMMAND_LENGTH; i++)
            {
                res += valid[rnd.Next(valid.Length)];
            }
            return res;
        }
    }
}